package com.smart.interact {

	import com.smart.events.touch.MoveEvent;
	import com.smart.events.touch.MoveEventHandler;
	
	import flash.display.InteractiveObject; 	

	// manages dragging and flicking  behavior 
	public class DragBehavior {			
				
		/// where touch takes place
		private var _target:InteractiveObject;
	
		// keep the handler
		private var _move_handler:MoveEventHandler;
		
		// the function being run, usually some sort of dispatch 
		private var _startdrag_func:Function; 	
		private var _stopdrag_func:Function; 
		private var _flick_func:Function;	
		
		// if we executed drag function or not 
		private var executed_drag_func:Boolean = false; 
		
		public function DragBehavior ( area:InteractiveObject = null , params:Object = null ) {

			if ( area != null && params != null ) {
				init(area,params); 
			}			
		}
		
		public function init ( area:InteractiveObject, params:Object ) : void {

			// parse the inputs 
			if ( params.start_drag != null ) {
				_startdrag_func = params.start_drag; 							
			}

			// parse the inputs 
			if ( params.stop_drag != null ) {
				_stopdrag_func = params.stop_drag; 							
			}

			// if flicking 
			if ( params.flick != null ) {
				_flick_func = params.flick; 							
			}
			
			// start doing work 
			_target = area; 
			register_touch(_target); 
						
		}
		
		private function register_touch (_target:InteractiveObject) : void {
					
			// register handler
			_move_handler = new MoveEventHandler(); 
			_move_handler.register(_target);
		
			_target.addEventListener(MoveEvent.MOVE_PRESS,on_press,false,0,true); 			
				
		}	
		
		private function on_press ( e:MoveEvent ) : void {
		
			debug("DragBehavior: PRESS "); 
			
			// no longer interested in press  
			_target.removeEventListener(MoveEvent.MOVE_PRESS,on_press); 
			// listen to these instead 
			_target.addEventListener(MoveEvent.MOVE_DRAG,on_drag,false,0,true); 
			_target.addEventListener(MoveEvent.MOVE_RELEASE,on_release,false,0,true); 
			_target.addEventListener(MoveEvent.MOVE_OUT,on_release,false,0,true); 
			_target.addEventListener(MoveEvent.MOVE_FLICK,on_flick,false,0,true); 
			
		}
		
		private function on_flick ( e:MoveEvent ) : void {
			if ( e.target == _target ) {				
				if ( _flick_func != null ) {
					_flick_func(_move_handler.flickDir,_move_handler.flickDistance);
				}
			}
		}
		
		private function on_drag ( e:MoveEvent ) : void {
		
			// execute the function for dragging only once 
			if ( e.target == _target && executed_drag_func == false ) {
				execute(_startdrag_func);
				executed_drag_func = true; 
			}
						
		}
		
		private function on_release ( e:MoveEvent ) : void {

			debug("DragBehavior: RELEASE " + e.target ); 
			
			if ( e.target != _target ) {
				return; 	
			}
			
			_target.addEventListener(MoveEvent.MOVE_PRESS,on_press,false,0,true); 
			_target.removeEventListener(MoveEvent.MOVE_DRAG,on_drag); 
			_target.removeEventListener(MoveEvent.MOVE_RELEASE,on_release); 
			_target.removeEventListener(MoveEvent.MOVE_OUT,on_release); 
			
			// only run stop drag if we actually started drag 
			if ( executed_drag_func ) {
				execute(_stopdrag_func); 
			} 
			
			// reset for next 
			executed_drag_func = false; 

		}
		
		// to call each function
		//  makes sure it is actually set 
		private function execute ( func:Function ) : void {
			if ( func != null ) {
				func(); 
			}
		}
		
		// enable or disable move events 
		public function register () : void {
			_move_handler.register(_target);	
		}
		
		public function unregister() : void {			
			_move_handler.unregister(); 			
			// remove all events 
			_target.removeEventListener(MoveEvent.MOVE_PRESS,on_press); 
			_target.removeEventListener(MoveEvent.MOVE_RELEASE,on_release); 
			_target.removeEventListener(MoveEvent.MOVE_OUT,on_release); 		
			_target.removeEventListener(MoveEvent.MOVE_DRAG,on_drag); 			
			_target.removeEventListener(MoveEvent.MOVE_FLICK,on_flick); 
		}
	
		// if we are debuggin or not 
		private var debug_mode:Boolean = false; 				
		private function debug ( str:String ) : void {		
			if ( debug_mode ) trace(str); 
		}		
	}
}